#include <linux/init.h>
#include <linux/module.h>

#include <linux/list.h>

static HLIST_HEAD(list_head);

typedef struct list_head_item {
    int v;
    struct hlist_node item_node;
} list_head_data_t;

static int __init hlist_hello_init(void)
{
    printk("[%s]: Hello World!\n", __func__);
    
    // 1. check lish empty
    printk("hlist is empty? %d\n", hlist_empty(&list_head));

    // 2. add item to list
    list_head_data_t data;
    data.v = 100;
    hlist_add_head(&data.item_node, &list_head);
    printk(KERN_INFO "hlist item added\n");

    // 3. check list empty again
    printk(KERN_INFO "hlist is empty? %d\n", hlist_empty(&list_head));


    // 4. traverse list, sum count
    int count = 0;
    struct hlist_node *pos;
    hlist_for_each(pos, &list_head) {
        list_head_data_t *x = hlist_entry(pos, list_head_data_t, item_node);
        printk(KERN_INFO "hlist item value: %d\n", x->v);
        count++;
    }
    printk(KERN_INFO "hlist item count: %d\n", count);

    // 5. delete item
    hlist_del(&data.item_node);
    printk(KERN_INFO "hlist item deleted\n");

    // 6. check list empty again
    printk(KERN_INFO "hlist is empty? %d\n", hlist_empty(&list_head));

    // 7. sum count again
    count = 0;
    hlist_for_each(pos, &list_head) {
        list_head_data_t *x = hlist_entry(pos, list_head_data_t, item_node);
        printk(KERN_INFO "hlist item value: %d\n", x->v);
        count++;
    }
    printk(KERN_INFO "hlist item count: %d\n", count);

    return 0;
}

static void __exit hlist_hello_exit(void)
{
    printk("[%s]: Bye!\n", __func__);
}

module_init(hlist_hello_init);
module_exit(hlist_hello_exit);

MODULE_LICENSE("GPL");